'use strict';
var MongoClient = require('mongodb').MongoClient;
var ObjectID = require('mongodb').ObjectID;
var mongodbConfig = require('./mongodbConfig');
var test = require('assert');

class mongodbClass{

    constructor(){
        this.mongodbUrl = mongodbConfig.mongodburl;
    }

    /**
     * 连接数据库
     * 
     * @param {any} callback 完成后执行的回调函数
     * 
     * @memberof mongodbClass
     */
    _connectDB(callback){
        MongoClient.connect(this.mongodbUrl,(err,db)=>{
            callback(err,db);
        });
    }

    _ObjectID(_id){
        return ObjectID(_id);
    }

    insert(colName,options){
        options = options || {};
        if(!options.docs){
            return;
        }
        var callback = options.callback || (()=>{});

        this._connectDB((err,db)=>{
            if(err){
                callback(err);
                return;
            }
            db.collection(colName).insert(options.docs,(err,result)=>{
                callback(err,result);
                db.close();
            });
        });
    }

    delete(colName, options){
        options = options || {};
        if(!options.filter){
            return;
        }
        var filter = options.filter || {};
        if(filter._id){
            filter._id = this._ObjectID(filter._id);
        }
        var fnName = options.multi ? 'deleteMany' : 'deleteOne';
        var callback = options.callback || (()=>{});
        this._connectDB((err, db) => {
            if(err){
                callback(err);
                return;
            }
            db.collection(colName)[fnName](filter,(err, result)=>{
                callback(err, result);
                db.close();
            });
        });
    }

    update(colName,options) {
        options = options || {};
        var filter = options.filter || {};
        if(filter._id){
            filter._id = this._ObjectID(filter._id);
        }
        var update = options.update || {};
        var fnName = options.multi ? 'updateMany' : 'updateOne';
        var callback = options.callback || (()=>{});

        var result = [];
        this._connectDB((err, db) => {
            if(err){
                callback(err);
                return;
            }
            db.collection(colName)[fnName](filter,update,(err, result) => {
                callback(err, result);
                db.close();
            });
        })
    }

    find(colName,options){
        options = options || {};
        var filter = options.filter || {};
        if(filter._id){
            filter._id = this._ObjectID(filter._id);
        }
        var skip = options.skip || 0;
        var limit = options.limit || 0;
        var sort = options.sort || {};
        var callback = options.callback || (()=>{});
        var result = [];
        this._connectDB((err, db) => {
            var cursor = db.collection(colName).find(filter).skip(skip).limit(limit).sort(sort);
            cursor.each((err, doc) => {
                if (err) {
                    callback(err, null);
                    db.close();
                    return;
                }
                if (doc != null) {
                    result.push(doc); 
                } else {
                    callback(null, result);
                    db.close();
                }
            });
        });
    }

    count(colName,options){
        var filter = options.filter || {};
        var callback = options.callback || (()=>{});

        this._connectDB((err, db) => {
            if(err){
                callback(err);
                return;
            }
            db.collection(colName).count(filter,(err,result)=>{
                callback(err,result);
            });
        })
    }

    static getInstance(){
        if(!this.instance){
            this.instance = new this();
        }
        return this.instance;
    }
}

module.exports = mongodbClass.getInstance();